﻿using System;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using Xunit;

namespace Fadd
{
	/// <summary>
	/// Generic logger interface.
	/// </summary>
	/// <remarks>
	/// <para>Used since we do not want to force everyone to use the Fadd.Logging framework.
	/// Implement your own proxy to use your favorite logging mechanism
	/// </para>
	/// </remarks>
	public interface IGenericLogger
	{

		void Trace(string message);
		void Trace(string message, Exception err);
		void Debug(string message);
		void Debug(string message, Exception err);
		void Info(string message);
		void Info(string message, Exception err);
		void Warning(string message);
		void Warning(string message, Exception err);
		void Error(string message);
		void Error(string message, Exception err);
	}

	public class ConsoleLogger : IGenericLogger
	{
		public void Trace(string message)
		{
			Write(ConsoleColor.DarkGray, message, null);
		}

		public void Trace(string message, Exception err)
		{
			Write(ConsoleColor.DarkGray, message, null);
		}

		public void Debug(string message)
		{
			Write(ConsoleColor.Gray, message, null);
		}

		public void Debug(string message, Exception err)
		{
			Write(ConsoleColor.Gray, message, null);
		}

		public void Info(string message)
		{
			Write(ConsoleColor.White, message, null);
		}

		public void Info(string message, Exception err)
		{
			Write(ConsoleColor.White, message, null);
		}

		public void Warning(string message)
		{
			Write(ConsoleColor.Cyan, message, null);
		}

		public void Warning(string message, Exception err)
		{
			Write(ConsoleColor.Cyan, message, null);
		}

		public void Error(string message)
		{
			Write(ConsoleColor.Red, message, null);
		}

		public void Error(string message, Exception err)
		{
			Write(ConsoleColor.Red, message, null);
		}

		private void Write(ConsoleColor color, string message, string exception)
		{
			StackFrame frame = new StackFrame(2);
			string stackFrame;
			MethodBase method = frame.GetMethod();
			if (method == null)
				stackFrame = string.Empty;
			else
				if (method.ReflectedType != null)
					stackFrame = method.ReflectedType.Name + "." + method.Name + "()";
				else
					stackFrame = "UnknownType." + method.Name + "()";

			ConsoleColor oldColor = Console.ForegroundColor;
			Console.ForegroundColor = color;
			Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + " " + Thread.CurrentThread.ManagedThreadId.ToString("000") + " " + stackFrame.PadRight(40) + message);
			if (exception != null)
				Console.WriteLine(exception);
			Console.ForegroundColor = oldColor;
		}

		[Fact]
		private void Test()
		{
			ConsoleLogger logger = new ConsoleLogger();
			logger.Info("Testing!!!");
		}
	}

	public class GenericNullLogger : IGenericLogger
	{
		public void Trace(string message)
		{
			
		}

		public void Trace(string message, Exception err)
		{
			
		}

		public void Debug(string message)
		{
			
		}

		public void Debug(string message, Exception err)
		{
			
		}

		public void Info(string message)
		{
			
		}

		public void Info(string message, Exception err)
		{
			
		}

		public void Warning(string message)
		{
			
		}

		public void Warning(string message, Exception err)
		{
			
		}

		public void Error(string message)
		{
			
		}

		public void Error(string message, Exception err)
		{
			
		}

		private GenericNullLogger()
		{}

		public static readonly GenericNullLogger Instance = new GenericNullLogger();

	}
}
